package zip

import (
	"archive/zip"
	"io"
	"os"
	"path/filepath"
	"strings"

	msio "gitee.com/yrwy/msgo/pkg/io"
	"gitee.com/yrwy/msgo/pkg/strs"
)

func Compress(destZip string, src ...string) error {
	zipfile, err := os.Create(destZip)
	if err != nil {
		return err
	}
	defer func() {
		zipfile.Close()
		if err != nil {
			os.Remove(destZip)
		}
	}()

	w := zip.NewWriter(zipfile)
	defer w.Close()
	for _, srcFile := range src {
		baseDir := filepath.Dir(srcFile) + "/"
		baseDir = strings.ReplaceAll(baseDir, "\\", "/")
		err = filepath.Walk(srcFile, func(path string, info os.FileInfo, err error) error {
			if path == "." || path == ".." {
				return nil
			}
			if err != nil {
				return err
			}
			//获取压缩头信息
			header, err := zip.FileInfoHeader(info)
			if err != nil {
				return err
			}
			path = strings.ReplaceAll(path, "\\", "/") //必须使用正斜杠而不是反斜杠
			header.Name = strings.TrimPrefix(path, baseDir)
			if info.IsDir() {
				header.Name += "/"
			} else {
				header.Method = zip.Deflate //指定文件压缩方式，默认为Store方式，该方式不压缩文件，只是转换为zip保存
			}
			writer, err := w.CreateHeader(header)
			if err != nil {
				return err
			}
			if !info.IsDir() {
				file, err := os.Open(path)
				if err != nil {
					return err
				}
				defer file.Close()
				_, err = io.Copy(writer, file)
				return err
			}
			return err
		})
	}
	return err
}

func _decompress(r *zip.Reader, destDir string) ([]string, error) {
	//判断压缩包为一个文件夹
	//if len(r.File) == 1 && r.File[0].FileInfo().IsDir() && filepath.Base(destDir) == r.File[0].Name {

	//}
	files := make([]string, 0, len(r.File))
	for _, f := range r.File {
		name := f.Name
		if f.NonUTF8 {
			name2, err := strs.GBKToUTF8(name)
			if err != nil {
				return nil, err
			}
			name = name2
		}
		fpath := filepath.Join(destDir, f.Name)
		if f.FileInfo().IsDir() {
			err := os.MkdirAll(fpath, 0755)
			if err != nil {
				return nil, err
			}
		} else {
			if err := os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
				return nil, err
			}
			inFile, err := f.Open()
			if err != nil {
				return nil, err
			}
			defer inFile.Close()
			outFile, err := msio.Create(fpath, f.Mode())
			if err != nil {
				return nil, err
			}
			defer outFile.Close()

			_, err = io.Copy(outFile, inFile)
			if err != nil {
				return nil, err
			}
			files = append(files, fpath)
		}
	}
	return files, nil
}
func DecompressReaderAt(reader io.ReaderAt, size int64, destDir string) ([]string, error) {
	r, err := zip.NewReader(reader, size)
	if err != nil {
		return nil, err
	}
	return _decompress(r, destDir)
}

func Decompress(srcZip string, destDir string) ([]string, error) {
	r, err := zip.OpenReader(srcZip)
	if err != nil {
		return nil, err
	}
	defer r.Close()
	return _decompress(&r.Reader, destDir)
}
